# -*- coding:utf-8 -*-
import os
import sys
import json
import yaml
import requests
import socket
import shutil
import zipfile


from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *




class SoftWidget(QWidget):
    """
    单个插件显示组件
    """
    send_Signal = pyqtSignal(dict)
    # info_Signal = pyqtSignal(dict)
    def __init__(self,data):
        super(SoftWidget, self).__init__()

        self.data = data
        self.status_color_map = {'更新':'#FFA500','最新':"#00FF00",'下载':'#A9A9A9'}  #版本不是最新版则显示old,最新则显示newest,
        #没有该插件则显示下载

        self.mid_font = QFont('',10,64)
        self.min_font = QFont('',10,20)

        self.btn_style = """QPushButton{color:black}
                                  QPushButton:hover{color:red}
                                 QPushButton{background-color:%s}
                                  QPushButton{border:2px}
                                  QPushButton{border-radius:3px}
                                  QPushButton{padding:1px 1px}""" % self.status_color_map[data['status']]

        self.info_style = """QPushButton{color:black}
                                  QPushButton:hover{color:#F5F5F5}
                                 QPushButton{background-color:#A9A9A9}
                                  QPushButton{border:2px}
                                  QPushButton{border-radius:3px}
                                  QPushButton{padding:1px 1px}"""

        # self.comb_style = """QComboBox QAbstractItemView::item{height:80px;}
        #                     QComboBox{border: 0px}
        #
        #                   """#QComboBox{background:} # QComboBox{selection-background-color: #B0C4DE;}

        self.comb_style ="""QComboBox QAbstractItemView::item{height:135px}
                            QComboBox{border: 0px}
                            QComboBox ::drop-down{border-top-right-radius: 13px}
                            QComboBox{font-size:12px}
                        """#   ;background: #B0C4DE;color:#E8E8E8               QComboBox{background: #1C1C1C;color:#B0C4DE}  QComboBox{background: #A9A9A9}

        self.comb_style = """ QComboBox{border: 0px}
                              QComboBox{selection-background-color: #B0C4DE}"""
        self.comb_style = """ QComboBox{font-size:12px}
                              QComboBox{selection-background-color: #A9A9A9}"""
        self.comb_style = """ QComboBox::drop-down{border-top-right-radius: 3px}
                            QComboBox QAbstractItemView::item{height:25px}
                            QComboBox{border: 0px}
                            QComboBox{font-size:12px}"""

        self.setFixedWidth(140)
        self.main_layout = QVBoxLayout()
        self.main_layout.setAlignment(Qt.AlignTop)
        self.name_label = QLabel(data['name'])
        self.name_label.setFont(self.mid_font)
        self.name_label.setAlignment(Qt.AlignCenter)
        self.version_comb = QComboBox()
        self.version_comb.setView(QListView())
        self.version_comb.setStyleSheet(self.comb_style)
        self.init_version_comb(self.data)
        self.version_comb.currentTextChanged.connect(self._changed)
        self.status_btn = QPushButton(data['status'])
        self.status_btn.clicked.connect(self._send_update)
        self.status_btn.setStyleSheet(self.btn_style)
        self.info_btn = QPushButton('版本信息')
        self.info_btn.clicked.connect(self._send_info)
        self.info_btn.setStyleSheet(self.info_style)
        self.main_layout.addWidget(self.name_label)
        self.main_layout.addWidget(self.version_comb)
        self.main_layout.addWidget(self.status_btn)
        self.main_layout.addWidget(self.info_btn)
        self.setLayout(self.main_layout)


    def init_version_comb(self,data):
        if data:
            version_data = data.get('version_data',{})
            if version_data:
                versions = sorted(version_data.keys(),reverse=True)
                self.version_comb.addItems(versions)

    def _changed(self,verision):
        print(verision)
        version_data = self.data.get('version_data', {})
        versions = sorted(version_data.keys(), reverse=True)
        if self.data['status'] != '下载':
            # if self.data['status'] == "更新":
            # if verision == versions[0]:
            #     status = "最新"
            # else:
            #     status = "更新"
            btn_style = """QPushButton{color:black}
                                      QPushButton:hover{color:red}
                                     QPushButton{background-color:%s}
                                      QPushButton{border:2px}
                                      QPushButton{border-radius:3px}
                                      QPushButton{padding:1px 1px}""" % self.status_color_map[self.data['status']]
            self.status_btn.setText(self.data['status'])
            self.status_btn.setStyleSheet(btn_style)
        else:
            pass

    def _send_update(self):
        print('_send_update:',self.data)
        HOST = self.data['HOST']
        PORT = self.data['PORT']  #这里的服务器信息是zip所在服务的信息
        selected_version = self.version_comb.currentText()
        zip_path = self.data['server_path']+'/'+selected_version+"/"+self.data['plugin_name']+'.zip'
        version_path = self.data['server_path']+'/'+selected_version+"/version.txt"
        zip_url = "http://{}:{}/{}".format(HOST,PORT,zip_path)
        version_url = "http://{}:{}/{}".format(HOST,PORT,version_path)
        print('zip_url:',zip_url)
        print('version_url:',version_url)
        
        client_path = self.data['client_path']
        local_Pulgins_path = os.path.dirname(client_path) #本地插件也就是Plugins目录
        os.makedirs(local_Pulgins_path,exist_ok=True)
        local_zip_path = os.path.join(local_Pulgins_path,self.data['plugin_name']+'.zip')  #下载到本地的zip文件路径
        plugin_dir = os.path.join(local_Pulgins_path,self.data['plugin_name'])  #本地插件目录
        os.makedirs(plugin_dir, exist_ok=True)
        #下载插件
        plugin_zip = requests.get(zip_url)
        with open(local_zip_path, "wb") as zw:  # 下载最新版的脚本
            zw.write(plugin_zip.content)
        print('zip下载完成')
        #解压插件
        z = zipfile.ZipFile(local_zip_path, 'r')
        z.extractall(plugin_dir)   #将该zip解压到本地该插件目录下
        z.close()
        print('zip解压完成')
        #删除zip文件
        os.remove(local_zip_path)
        print('zip删除完成')
        #
        #下载版本信息文件，直接下载到插件目录
        version_txt = requests.get(version_url)
        local_version_path = os.path.join(plugin_dir,'version.txt')
        with open(local_version_path, "wb") as vw:  # 下载最新版的脚本
            vw.write(version_txt.content)
        print('version.txt下载完成')
        
        #更新显示
        download_version_data = {}
        with open(local_version_path,'r',encoding='utf8') as r:
            download_version_data = eval(r.read())
        download_verion = download_version_data.get('version')
        if download_verion == self.data['lastest_version']:
            self.data['status'] = '最新'
        else:
            self.data['status'] = '更新'
        self._changed(download_verion)
        print('下载完成')

    def _send_info(self):

        current_version = self.version_comb.currentText()

        info = self.data['version_data'].get(current_version,'版本错误')

        # print(info)
        QMessageBox.information(None,'版本信息',str(info))




class Softlayout(QWidget):
    """
    每页当中，拍成一行的组件
    """
    def __init__(self,data_list):
        super(Softlayout, self).__init__()

        self.main_layout = QHBoxLayout()
        self.main_layout.setAlignment(Qt.AlignLeft)
        self.init_data(data_list)
        self.setLayout(self.main_layout)

    def init_data(self,data_list):
        if data_list:
            for data in data_list:
                sw = SoftWidget(data)

                self.main_layout.addWidget(sw)





class AutoUpdate(QWidget):

    def __init__(self):
        super(AutoUpdate, self).__init__()

        self.max_row = 4
        self.max_column = 4
        self.max_per_page = self.max_row*self.max_column

        self.page_btn_style = """QPushButton{color:black}
                                  QPushButton:hover{color:#F5F5F5}
                                 QPushButton{background-color:#A9A9A9}
                                  QPushButton{border:2px}
                                  QPushButton{border-radius:3px}
                                  QPushButton{padding:1px 1px}"""
        self.choose_page_btn_style = """QPushButton{color:	#FFFFFF}
                                        QPushButton:hover{color:#F5F5F5}
                                        QPushButton{background-color:#A9A9A9}
                                        QPushButton{border:2px}
                                        QPushButton{border-radius:3px}
                                        QPushButton{padding:1px 1px}"""

        self.page_btn_list = []  #page btn列表

        self.page_clips = []  #页面拆分
        self.page_map = {}  #页面窗口映射
        self.current_page = None  #当前页面

        self.setWindowTitle('插件管理')
        self.setMinimumHeight(500)
        self.main_layout = QVBoxLayout()


        self.plugin_layout = QVBoxLayout()  #插件layout
        self.plugin_layout.setAlignment(Qt.AlignTop)


        # self.main_layout.addWidget(self.plugin_layout)
        data_list = [{'plugin_name':'ForMac','name':'排期软件','server_path':'/timeaxis/ForMac','client_path':'C:/timeaxis_my_task','status':'下载'},
                     {'plugin_name':'ForMac','name':'排期软件','server_path':'/timeaxis/ForMac','client_path':'C:/timeaxis_my_task','status':'更新'},
                     {'plugin_name':'ForMac','name':'排期软件','server_path':'/timeaxis/ForMac','client_path':'C:/timeaxis_my_task','status':'最新'},
                     {'plugin_name':'ForMac','name':'排期软件','server_path':'/timeaxis/ForMac','client_path':'C:/timeaxis_my_task','status':'下载'},
                     {'plugin_name':'ForMac','name':'排期软件','server_path':'/timeaxis/ForMac','client_path':'C:/timeaxis_my_task','status':'最新'},
                     {'plugin_name':'ForMac','name':'排期软件','server_path':'/timeaxis/ForMac','client_path':'C:/timeaxis_my_task','status':'最新'},
                     {'plugin_name':'ForMac','name':'排期软件','server_path':'/timeaxis/ForMac','client_path':'C:/timeaxis_my_task','status':'最新'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '下载'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '更新'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '最新'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '下载'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '最新'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '最新'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '下载'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '更新'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '最新'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '下载'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '最新'},
                     {'plugin_name': 'ForMac', 'name': '排期软件', 'server_path': '/timeaxis/ForMac',
                      'client_path': 'C:/timeaxis_my_task', 'status': '最新'},
                     ]

        plugin_data = {'ForMac': {'name': 'Mac版排期', 'server_path': '/Users/lansai/Plugins/ForMac',
                                  'client_path': 'F:/Plugins/ForMac',
                                  'version_data': {'20210520.1.12': {'version': '20210520.1.12', 'update': '更新1'},
                                                   '20210520.2.05': {'version': '20210520.2.05', 'update': '更新2'}}},
                       'maya_pipeline': {'name': 'maya项目管理插件', 'server_path': '/Users/lansai/Plugins/maya_pipeline',
                                         'client_path': 'F:/Plugins/maya_pipeline',
                                         'version_data': {'20210501.0.002': {'version': '20210501.0.002', 'update': '更新1'},
                                                          '20210501.02.112': {'version': '20210501.02.112', 'update': '更新3'},
                                                          '20210501.05.122': {'version': '20210501.05.122', 'update': '更新4'},
                                                          '20210501.1.012': {'version': '20210501.1.012', 'update': '更新2'}}},
                       'backend': {'name': '数据备份', 'server_path': '/Users/lansai/Plugins/maya_pipeline',
                                   'client_path': 'F:/Plugins/maya_pipeline',
                                   'version_data': {'20210501.0.002': {'version': '20210501.0.002', 'update': '更新1'},
                                                    '20210501.02.112': {'version': '20210501.02.112', 'update': '更新3'},
                                                    '20210501.05.122': {'version': '20210501.05.122', 'update': '更新4'},
                                                    '20210501.1.012': {'version': '20210501.1.012', 'update': '更新2'}}}}


        # self.page_map = self.init_page_map(data_list)
        local_config_info = self.get_server_info()
        self.local_server_info = local_config_info.get('SERVER_INFO',{})
        # print('local_server_info:',self.local_server_info)
        self.local_zip_info = local_config_info.get('ZIP_INFO',{})

        self.plugin_data = self.request_plugin_info(self.local_server_info)
        self.data_list = self.local_compare(self.plugin_data,self.local_zip_info)
        self.page_map = self.init_page_map(self.data_list)
        self.current_page = self.page_map[0]
        self.current_page.setHidden(False)
        self.plugin_layout.addWidget(self.current_page)

        self.main_layout.addLayout(self.plugin_layout)
        self.page_layout = QHBoxLayout()
        self.init_page(len(self.data_list),self.max_column)


        self.setLayout(self.main_layout)

    def get_server_info(self):
        """
        读取本地yaml，读取服务器信息
        :return:
        """
        local_yaml_path = os.path.join(os.path.dirname(__file__), 'local_config.yaml')
        stream = open(local_yaml_path, mode='r', encoding='utf8')
        data = yaml.load(stream, Loader=yaml.FullLoader)
        stream.close()
        # print('yaml.datatype:',type(data))
        # print('get_server_info:',data)

        return data

    def request_plugin_info(self,SERVER_INFO):
        data = {}
        # SERVER_INFO = server_data.get('SERVER_INFO','')
        # ZIP_INFO = server_data.get('ZIP_INFO','')
        if SERVER_INFO:
            HOST = SERVER_INFO.get('HOST','')
            PORT = SERVER_INFO.get('PORT',None)
            BUFFER = SERVER_INFO.get('PORT',None)
            sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            sock.settimeout(0.95)
            msg = {'ask_type':'plugin'}
            # print('request_plugin_info  001')
            try:
                sock.connect((HOST,PORT))
                # print('request_plugin_info  002')
                # sock.send(json.dumps(msg).encode())
                sock.send(str(msg).encode())
                # print('request_plugin_info  003')
                all_backs = b''
                while True:
                    print('接收中....')
                    back = sock.recv(BUFFER)  # socket.MSG_WAITALL#,socket.MSG_WAITALL
                    print('接受回来')
                    if not back:
                        break
                    all_backs += back
            except Exception as request_plugin_info_ERR:
                print('request failed',str(request_plugin_info_ERR))

            finally:
                # data = json.loads(all_backs.decode('utf8'))

                data = eval(all_backs.decode('utf8'))
                # print('request_plugin_info:',data)
                sock.close()
        return data #,ZIP_INFO

    def local_compare(self,plugin_data,local_zip_info):
        data_list = []
        if plugin_data:
            for plugin,info in plugin_data.items():
                info.update(local_zip_info)
                info['plugin_name'] = plugin
                client_path = info['client_path']
                version_data = info['version_data']
                version_list = sorted(list(version_data.keys()))
                lastest_version = version_list[-1]
                info['lastest_version'] = lastest_version
                status = '下载'
                if os.path.exists(client_path):
                    local_version_path = os.path.join(client_path,'version.txt')
                    version_info = {}
                    with open(local_version_path,'r',encoding='utf8') as r:
                        version_info = eval(r.read())
                    local_version = version_info.get('version',"")

                    if local_version != lastest_version:
                        status = '更新'
                    else:
                        status = '最新'
                info['status'] = status
                data_list.append(info)

        return data_list



    def create_pages(self,page):
        soft_layout_list = []
        clips = self.clip_list(page,self.max_column)
        for datalist in clips:
            sl = Softlayout(datalist)
            soft_layout_list.append(sl)
        return soft_layout_list

    def init_page_map(self,data_list):

        page_map = {}
        page_clip = self.clip_list(data_list,self.max_per_page)
        for p in range(len(page_clip)):
            page_frame = QFrame()
            page_frame_layout = QVBoxLayout()
            page = page_clip[p]
            softlayouts = self.create_pages(page)
            for i in softlayouts:
                page_frame_layout.addWidget(i)
            page_frame.setLayout(page_frame_layout)
            page_frame.setHidden(True)
            page_map[p] = page_frame
        return page_map


        # plugin_frame = QFrame()
        # plugin_frame_layout = QHBoxLayout()
        #
        #
        # plugin_frame.setLayout(plugin_frame_layout)
        #
        # first_page = page_clip[0]
        # clips = self.clip_list(first_page,self.max_column)
        # for datalist in clips:
        #     sl = Softlayout(datalist)
        #     self.plugin_layout.addWidget(sl)



    def clip_list(self,origin_list, c):  # a为原列表，c为等分长度
        clip_back = []
        if len(origin_list) > c:
            for i in range(int(len(origin_list) / c)):
                clip_a = origin_list[c * i:c * (i + 1)]
                clip_back.append(clip_a)
            # last 剩下的单独为一组
            last = origin_list[int(len(origin_list) / c) * c:]
            if last:
                clip_back.append(last)
        else:  # 如果切分长度不小于原列表长度，那么直接返回原列表
            clip_back = [origin_list]

        return clip_back


    def init_page(self,plugin_counts,rows):
        max_counts = self.max_row*self.max_column
        counts = plugin_counts//max_counts
        for i in range(counts+1):
            btn = QPushButton(str(i))
            btn.clicked.connect(self._choose_page)
            btn.setFixedWidth(20)
            btn.setStyleSheet(self.page_btn_style)
            if i == 0:
                btn.setStyleSheet(self.choose_page_btn_style)
            self.page_layout.addWidget(btn)
            self.page_btn_list.append(btn)
        self.page_layout.setAlignment(Qt.AlignBottom|Qt.AlignCenter)
        self.main_layout.addLayout(self.page_layout)


    def _choose_page(self):
        btn = self.sender()
        index = int(btn.text())
        for i in self.page_btn_list:
            i.setStyleSheet(self.page_btn_style)
        btn.setStyleSheet(self.choose_page_btn_style)

        for k,v in self.page_map.items():
            v.setHidden(True)
        self.current_page = self.page_map[index]
        self.current_page.setHidden(False)
        self.plugin_layout.addWidget(self.current_page)


    def request_from_222(self,msg):
        """
        request data from 222
        :param msg: {'ask_type':xxx,''}
        :return:
        """

        print(msg)

        #print(msg)

        data={}
        sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        sock.settimeout(0.95)
        try:
            sock.connect((self.HOST,self.PORT))
            sock.send(str(msg).encode())
            all_backs = b''
            while True:
                #time.sleep(0.1)
                print('接收中....')
                back = sock.recv(self.BUFFER)  # socket.MSG_WAITALL#,socket.MSG_WAITALL
                # # header_len=struct.unpack(back)

                #print('接受回来:')

                #print('接受回来:', back)
                print('接受回来')

                if not back:
                    break
                all_backs += back


        except Exception as request_from_222_ERR:
            print('request failed')
            print(str(request_from_222_ERR))
        finally:
            data = eval(all_backs.decode('utf8'))

            print(data)

            #print(data)

            sock.close()

        return data

if __name__ == '__main__':
    app = QApplication(sys.argv)
    a = AutoUpdate()
    a.show()
    sys.exit(app.exec_())